package com.leo;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.util.Arrays;
import java.util.List;

/**
 * @BelongsProject: leo-emailfx
 * @BelongsPackage: com.leo
 * @Author: wangss
 * @CreateTime: 2023-03-13  23:06
 * @Description: TODO
 * @Version: 1.0
 */
public class TreeViewEditAdd extends Application {
    //    private final Node rootIcon = new ImageView(new Image(getClass().getResourceAsStream("folder_16.jpg")));//创建根节点图形图像对象
//    private final Image depIcon = new Image(getClass().getResourceAsStream("folder_16.jpg"));//创建部门节点的外观图片
    List<Employee> employees = Arrays.<Employee>asList(
            new Employee("Jacob Smith", "Accounts Department"),
            new Employee("Isabella Johnson", "Accounts Department"),
            new Employee("Ethan Williams", "Sales Department"),
            new Employee("Emma Jones", "Sales Department"),
            new Employee("Michael Brown", "Sales Department"),
            new Employee("Anna Black", "Sales Department"),
            new Employee("Rodger York", "Sales Department"),
            new Employee("Susan Collins", "Sales Department"),
            new Employee("Mike Graham", "IT Support"),
            new Employee("Judy Mayer", "IT Support"),
            new Employee("Gregory Smith", "IT Support"));//创建员工实体的List<Employee>类型对象
    TreeItem<String> rootNode = new TreeItem<>("根节点元素");//根节点选项元素的创建

    public static void main(String[] args) {
        Application.launch(args);//javaFx程序的启动
    }

    @Override
    public void start(Stage stage) {
        rootNode.setExpanded(true);//根节点元素默认展开
        for (Employee employee : employees) {
            TreeItem<String> empLeaf = new TreeItem<>(employee.getName());//树形结构的节点选项都添加文本内容
            boolean found = false;
            for (TreeItem<String> depNode : rootNode.getChildren()) {//获取部门节点
                if (depNode.getValue().contentEquals(employee.getDepartment())) {//部门名称匹配的节点元素添加到部门节点下作为叶子节点
                    depNode.getChildren().add(empLeaf);//添加叶子节点到部门节点上
                    found = true;
                    break;
                }
            }
            if (!found) {
                TreeItem depNode = new TreeItem(employee.getDepartment());//部门节点选项的创建
                rootNode.getChildren().add(depNode);//根节点添加部门节点
                depNode.getChildren().add(empLeaf);//部门节点上添加叶子节点
            }
        }

        stage.setTitle("测试树形结构添加");
        VBox box = new VBox();//垂直布局盒子对象的创建
        final Scene scene = new Scene(box, 400, 300);//场景对象的创建
        scene.setFill(Color.LIGHTGRAY);//设置场景填充颜色

        TreeView<String> treeView = new TreeView<>(rootNode);//创建树形结构并挂载根节点选项
        treeView.setEditable(true);//设置树形结构可编辑
        treeView.setCellFactory((TreeView<String> p) -> new TextFieldTreeCellImpl());//将treeView对象的选项节点元素设置成自定义的TreeCell实现

        box.getChildren().add(treeView);//垂直盒子布局对象添加treeView组件
        stage.setScene(scene);//舞台设置场景
        stage.show();//舞台展现
    }

    private final class TextFieldTreeCellImpl extends TreeCell<String> {

        //文本域外观组件对象
        private TextField textField;
        //上下文菜单对象的创建
        private final ContextMenu addMenu = new ContextMenu();

        public TextFieldTreeCellImpl() {
            //上下文菜单选项对象的创建
            MenuItem addMenuItem = new MenuItem("添加节点");
            //将该选项添加至菜单
            addMenu.getItems().add(addMenuItem);
            //设置菜单选项组件对象的鼠标点击事件处理回调函数
            addMenuItem.setOnAction(event -> {
                TreeItem newEmployee = new TreeItem<>("New Employee");//创建一个树形结构选项节点选项对象
                getTreeItem().getChildren().add(newEmployee);//树形选项集合中添加树形选项节点对象
            });
        }

        //实现继承自TreeCell类的同名模板方法
        @Override
        public void startEdit() {
            //调用父类同名开始编辑模板方法
            super.startEdit();

            //如果文本域对象为空则创建一个
            if (textField == null) {
                createTextField();
            }
            //设置文本内容
            setText(null);
            //设置编辑节点的图形元素为textField对象
            setGraphic(textField);
            //文本域节点获取焦点选择
            textField.selectAll();
        }

        //取消编辑
        @Override
        public void cancelEdit() {
            //调用模板类的取消编辑指令
            super.cancelEdit();

            //获取当前选项为所选文字
            setText(getItem());
            //设置当前选中节点为选中的外观图形元素
            setGraphic(getTreeItem().getGraphic());
        }

        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);//修改选择节点

            if (empty) {//当没有选择的时候
                setText(null);//若修改内容为空则选中节点内容设为null
                setGraphic(null);//设置选择的外观节点为null
            } else {
                if (isEditing()) {//判断是否是在编辑
                    if (textField != null) {//判断选择编辑的文本内容是否为null
                        textField.setText(getString());//若不为空，则设置文本域的文本内容为所选择的内容
                    }
                    setText(null);//设置文本内容为空
                    setGraphic(textField);//设置外观组件为前文定义的textField对象
                } else {
                    setText(getString());//设置TextFieldTreeCellImpl对象的文本内容为所选文本内容
                    setGraphic(getTreeItem().getGraphic());//设置TextFieldTreeCellImpl对象的外观图形为所选树形结构节点的图形外观
                    //判断不是叶子节点且有父亲节点
                    if (!getTreeItem().isLeaf() && getTreeItem().getParent() != null) {
                        //设置上下文菜单添加菜单对象
                        setContextMenu(addMenu);
                    }
                }
            }
        }

        private void createTextField() {
            //创建文本域对象取值为TextFieldTreeCellImpl类型treeCell对象选择的文本内容
            textField = new TextField(getString());
            //textField对象的键盘释放事件监听处理回调函数
            textField.setOnKeyReleased((KeyEvent t) -> {
                //判断键盘事件对应的键位
                if (t.getCode() == KeyCode.ENTER) {
                    //如果是回车键则提交文本区域内容作为树形结构节点选项的提交编辑内容
                    commitEdit(textField.getText());
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    //当按的键盘键位是esc键就取消编辑功能
                    cancelEdit();
                }
            });
        }

        //利用继承的模板方法获取选项的选择文本内容
        private String getString() {
            return getItem() == null ? "" : getItem();
        }
    }

    public static class Employee {//pojo类型的domain类型定义

        private final SimpleStringProperty name;//同String的用法
        private final SimpleStringProperty department;//同String的用法

        private Employee(String name, String department) {//构造函数的定义
            this.name = new SimpleStringProperty(name);
            this.department = new SimpleStringProperty(department);
        }

        public String getName() {
            return name.get();
        }

        public void setName(String fName) {
            name.set(fName);
        }

        public String getDepartment() {
            return department.get();
        }

        public void setDepartment(String fName) {
            department.set(fName);
        }
    }
}
